#include "event_app.h"
#include "sound_board.h"
#include "wt588f_board.h"
#include "device_parameter.h"

#if _VOICE_PLAY_TYPE_ == _VOICE_PLAY_SPEAKER_

/**
 * @brief 繁忙状态信号线初始化
 *
 */
static void Wt588fBusyConfiguration(void);

/**
 * @brief 数据线初始化
 *
 */
static void Wt588fDataConfiguration(void);

/**
 * @brief 电源控制管脚初始化
 *
 */
static void Wt588fPowerContorlConfiguration(void);

/**
 * @brief 设置数据线输出高电平
 *
 */
static void Wt588fSetDataHighLevel(void);

/**
 * @brief 设置数据线输出低电平
 *
 */
static void Wt588fSetDataLowLevel(void);

/**
 * @brief 读取繁忙管脚电平
 *
 * @return bool - 管脚电平（true：高电平 false：低电平）
 */
static bool Wt588fReadBusyPinLevel(void);

/**
 * @brief 设置电源控制引脚为高电平
 *
 */
static void Wt588fSetPowerContorlHighLevel(void);

/**
 * @brief 设置电源控制引脚为低电平
 *
 */
static void Wt588fSetPowerContorlLowLevel(void);

/**
 * @brief 事件处理中心
 *
 */
static uint16_t Wt588fEventTaskCallback(uint8_t TaskId, uint16_t Events);

static uint8_t Wt588fEventTaskId = 0;
static Wt588fExternalInterfaces_t ExternalInterfaces = {0};

static void Wt588fBusyConfiguration(void)
{
#if _BOARD_TYPE_ == _V33_A_BOARD_
  GPIOB_ModeCfg(WT588F_BUSY_PIN, GPIO_ModeIN_PD);

#elif _BOARD_TYPE_ == _V33_B_BOARD_
  GPIOA_ModeCfg(WT588F_BUSY_PIN, GPIO_ModeIN_PD);

#elif _BOARD_TYPE_ == _V33_C_BOARD_
  GPIOB_ModeCfg(WT588F_BUSY_PIN, GPIO_ModeIN_PD);
#endif
}

static void Wt588fDataConfiguration(void)
{
#if _BOARD_TYPE_ == _V33_A_BOARD_
  GPIOB_ModeCfg(WT588F_DATA_PIN, GPIO_ModeOut_PP_20mA);

#elif _BOARD_TYPE_ == _V33_B_BOARD_
  GPIOA_ModeCfg(WT588F_DATA_PIN, GPIO_ModeOut_PP_20mA);

#elif _BOARD_TYPE_ == _V33_C_BOARD_
  GPIOB_ModeCfg(WT588F_DATA_PIN, GPIO_ModeOut_PP_20mA);
#endif

  Wt588fSetDataLowLevel();
}

static void Wt588fPowerContorlConfiguration(void)
{
#if _BOARD_TYPE_ == _V33_A_BOARD_
  GPIOB_ModeCfg(WT588F_POWER_CONTORL_PIN, GPIO_ModeOut_PP_20mA);

#elif _BOARD_TYPE_ == _V33_B_BOARD_
  GPIOA_ModeCfg(WT588F_POWER_CONTORL_PIN, GPIO_ModeOut_PP_20mA);
#endif

  Wt588fSetPowerContorlLowLevel();
}

static void Wt588fSetDataHighLevel(void)
{
#if _BOARD_TYPE_ == _V33_A_BOARD_
  GPIOB_SetBits(WT588F_DATA_PIN);

#elif _BOARD_TYPE_ == _V33_B_BOARD_
  GPIOA_SetBits(WT588F_DATA_PIN);

#elif _BOARD_TYPE_ == _V33_C_BOARD_
  GPIOB_SetBits(WT588F_DATA_PIN);
#endif
}

static void Wt588fSetDataLowLevel(void)
{
#if _BOARD_TYPE_ == _V33_A_BOARD_
  GPIOB_ResetBits(WT588F_DATA_PIN);

#elif _BOARD_TYPE_ == _V33_B_BOARD_
  GPIOA_ResetBits(WT588F_DATA_PIN);

#elif _BOARD_TYPE_ == _V33_C_BOARD_
  GPIOB_ResetBits(WT588F_DATA_PIN);
#endif
}

static bool Wt588fReadBusyPinLevel(void)
{
#if _BOARD_TYPE_ == _V33_A_BOARD_
  if (GPIOB_ReadPortPin(WT588F_BUSY_PIN) == WT588F_BUSY_PIN)
    return true;

#elif _BOARD_TYPE_ == _V33_B_BOARD_
  if (GPIOA_ReadPortPin(WT588F_BUSY_PIN) == WT588F_BUSY_PIN)
    return true;

#elif _BOARD_TYPE_ == _V33_C_BOARD_
  if (GPIOB_ReadPortPin(WT588F_BUSY_PIN) == WT588F_BUSY_PIN)
    return true;
#endif

  return false;
}

static void Wt588fSetPowerContorlHighLevel(void)
{
#if _BOARD_TYPE_ == _V33_A_BOARD_
  GPIOB_SetBits(WT588F_POWER_CONTORL_PIN);

#elif _BOARD_TYPE_ == _V33_B_BOARD_
  GPIOA_SetBits(WT588F_POWER_CONTORL_PIN);
#endif
}

static void Wt588fSetPowerContorlLowLevel(void)
{
#if _BOARD_TYPE_ == _V33_A_BOARD_
  GPIOB_ResetBits(WT588F_POWER_CONTORL_PIN);

#elif _BOARD_TYPE_ == _V33_B_BOARD_
  GPIOA_ResetBits(WT588F_POWER_CONTORL_PIN);
#endif
}

static uint16_t Wt588fEventTaskCallback(uint8_t TaskId, uint16_t Events)
{
  if (Wt588fEventTaskId == TaskId)
  {
    if (Events & WT588F_AUDIO_PLAYBACK)
    {
      if (ExternalInterfaces.AudioPlaybackCallback != NULL)
      {
        ExternalInterfaces.AudioPlaybackCallback();
      }

      return (Events ^ WT588F_AUDIO_PLAYBACK);
    }
  }

  return 0;
}

void Wt588fDelayUs(uint16_t Us)
{
  DelayUs(Us);
}

void Wt588fDelayMs(uint16_t Ms)
{
  DelayMs(Ms);
}

bool Wt588fGetBusyPinLevel(void)
{
  return Wt588fReadBusyPinLevel();
}

uint8_t Wt588fGetVolumeLevel(void)
{
  return GetSystemVolumeLevel();
}

bool Wt588fGetDoNotDisturbFlag(void)
{
  return SoundGetDoNotDisturbFlag();
}

void Wt588fSetDataPinLevel(bool PinLevel)
{
  (PinLevel == true) ? Wt588fSetDataHighLevel() : Wt588fSetDataLowLevel();
}

bool Wt588fGetBusyStatus(void)
{
  return EventGetVoicePlayBusyFlagBit();
}

void Wt588fSetPowerContorlPinLevel(bool Level)
{
  (Level == true) ? Wt588fSetPowerContorlHighLevel() : Wt588fSetPowerContorlLowLevel();
}

void Wt588fSetBusyStatus(bool Status)
{
  EventSetVoicePlayBusyFlagBit(Status);
}

void Wt588fSendOneByte(uint8_t Byte)
{
  Wt588fSetDataLowLevel();
  Wt588fDelayMs(WT588F_WAIT_LEVEL_STABLE_TIME);

  for (uint8_t i = 0; i < 8; i++)
  {
    if (Byte & 0x01)
    {
      Wt588fSetDataHighLevel();
      Wt588fDelayUs(WT588F_BIT_HIGH_LEVEL_TIME);
      Wt588fSetDataLowLevel();
      Wt588fDelayUs(WT588F_BIT_LOW_LEVEL_TIME);
    }
    else
    {
      Wt588fSetDataHighLevel();
      Wt588fDelayUs(WT588F_BIT_LOW_LEVEL_TIME);
      Wt588fSetDataLowLevel();
      Wt588fDelayUs(WT588F_BIT_HIGH_LEVEL_TIME);
    }

    Byte >>= 1;
  }

  Wt588fSetDataHighLevel();
  Wt588fDelayMs(WT588F_WAIT_LEVEL_STABLE_TIME);
}

void Wt588fSendDataBuff(uint8_t *pDataIn, uint8_t SizeIn)
{
  if ((pDataIn != NULL) && (SizeIn > 0))
  {
    for (uint8_t i = 0; i < SizeIn; i++)
    {
      Wt588fSendOneByte(pDataIn[i]);
    }
  }
}

uint8_t *Wt588Malloc(uint16_t MallocSize)
{
  return tmos_msg_allocate(MallocSize);
}

void Wt588fFree(void *ptr)
{
  tmos_msg_deallocate((uint8_t *)ptr);
}

uint32_t Wt588fGetSystemClockTime(void)
{
  return RTC_GetCycle32k();
}

void Wt588fStopAudioPlaybackTask(void)
{
  tmos_stop_task(Wt588fEventTaskId, WT588F_AUDIO_PLAYBACK);
}

void Wt588fDelayedStartAudioPlaybackTask(uint32_t Ms)
{
  tmos_stop_task(Wt588fEventTaskId, WT588F_AUDIO_PLAYBACK);
  tmos_start_task(Wt588fEventTaskId, WT588F_AUDIO_PLAYBACK, MS1_TO_SYSTEM_TIME(Ms));
}

void Wt588fStartAudioPlaybackNoWait(void)
{
  tmos_stop_task(Wt588fEventTaskId, WT588F_AUDIO_PLAYBACK);
  tmos_set_event(Wt588fEventTaskId, WT588F_AUDIO_PLAYBACK);
}

void Wt588fBoardInitialization(Wt588fExternalInterfaces_t *pExternalInterfaces)
{
  ExternalInterfaces.AudioPlaybackCallback = pExternalInterfaces->AudioPlaybackCallback;
  Wt588fEventTaskId = TMOS_ProcessEventRegister(Wt588fEventTaskCallback);

  Wt588fBusyConfiguration();
  Wt588fDataConfiguration();
  Wt588fPowerContorlConfiguration();
}

#endif
